﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor
{
    /// <summary>
    /// 此类用于表示某道试题
    /// </summary>
    public class BaseQuestion
    {
        /// <summary>
        ///      这是一道选择题的文本，也是最初的原型：
        ///      试题＞＞【意大利】【资本主义萌芽】产生于【14、15】世纪。
        ///      　　答案＞＞意大利
        ///      　　解析＞＞也可说“西欧”。
        ///      　　错项＞＞中国
        ///      　　解析＞＞中国资本主义萌芽产生于明朝中后期。明朝14世纪才建立。
        ///      　　答案＞＞资本主义萌芽
        ///      　　解析＞＞
        ///      　　错项＞＞文艺复兴
        ///      　　解析＞＞文艺复兴的时间是14~17世纪。从语义上来说应是“开始于”而不是“产生于”。
        ///      　　答案＞＞14、15
        ///      　　解析＞＞
        ///      　　错项＞＞14~17
        ///      　　解析＞＞这是文艺复兴的时间
        ///      　　错项＞＞16~18
        ///      　　解析＞＞这是工场手工业时期。
        ///      　　错项＞＞1500年前后
        ///      　　解析＞＞这是新航路开辟的时间段。
        ///      〓〓〓〓〓〓
        /// </summary>
        /// <param name="baseQuestionText">表示一个包含一对或多对括弧的题干，一组或多组答案。</param>
        /// <param name="multiFillBlankQuestions">表示填空题是复合填空项还是单一填空项。</param>
        /// <param name="choiceItemsConfounded">是否混淆选择项，默认为 true。</param>
        public static List<Question> BuildQuestionList(string baseQuestionText, bool multiFillBlankQuestions = true, bool choiceItemsConfounded = true)
        {
            List<Question> questions = new List<Question>();

            #region 处理主观题
            if (baseQuestionText.Contains("＜＜材料＞＞"))
            {
                baseQuestionText = FormatSubjectiveText(baseQuestionText);  // 把答案中的换行符自动替换为 <br>

                int indexOfQuestion = baseQuestionText.IndexOf("＜＜问题＞＞");
                if (indexOfQuestion < 0) return questions;//光材料，没有问题。以后可以考虑做成提纲。现在直接跳过。

                List<string> questionPieces = new List<string>();

                string[] textPieces = baseQuestionText.Split(new string[1] { "\n＜＜材料" }, StringSplitOptions.RemoveEmptyEntries);

                StringBuilder sb = null;

                foreach (var s in textPieces)
                {
                    if (sb == null) sb = new StringBuilder();

                    if (s.StartsWith("＞＞"))
                    {
                        string text = sb.ToString();
                        if (text.Contains("答案＞＞"))
                        {
                            questionPieces.Add(text);//如果已经有了答案部分，再碰到“材料”，说明这则材料开始了新试题。
                            sb = null;
                            sb = new StringBuilder();
                            sb.Append("\n＜＜材料" + s);
                        }
                        else
                        {
                            sb.Append("\n＜＜材料" + s);
                        }
                    }
                    else
                    {
                        sb.Append(s.Substring(4));
                    }
                }

                string stText = sb.ToString();
                if (string.IsNullOrEmpty(stText) == false)
                {
                    questionPieces.Add(stText);
                }

                foreach (var s in questionPieces)
                {
                    if (s.Contains("\n＜＜材料＞＞") == false || s.Contains("\n＜＜问题＞＞") == false || s.Contains("答案＞＞") == false) continue;

                    int titleEndIndex = s.IndexOf("\n＜＜材料＞＞");

                    string title = string.Empty;
                    if (titleEndIndex >= 0)
                        title = s.Substring(0, titleEndIndex);

                    Question newQuestion = new Question(title);

                    string[] tts = s.Split(new string[1] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (var st in tts)
                    {
                        if (st.StartsWith("＜＜材料＞＞"))
                        {
                            newQuestion.Materials.Add(st);
                        }
                        else if (st.StartsWith("＜＜出处＞＞"))
                        {
                            string cl = newQuestion.Materials[newQuestion.Materials.Count - 1];
                            cl += st;
                            newQuestion.Materials[newQuestion.Materials.Count - 1] = cl;
                        }
                        else if (st.StartsWith("＜＜问题＞＞"))
                        {
                            newQuestion.AsksList.Add(st.Substring(6));
                        }
                        else if (st.StartsWith("　　答案＞＞"))
                        {
                            newQuestion.Answers.Add(st.Substring(6));
                        }
                        else if (st.StartsWith("　　解析＞＞"))
                        {
                            if (newQuestion.Answers.Count <= 0)
                                newQuestion.Answers.Add("");

                            newQuestion.Answers[newQuestion.Answers.Count - 1] += "　　解析＞＞" + st.Substring(6);  // 这个不能直接加——因为要受答案的限制！
                        }
                        else
                        {
                            // 跨行的只应该是二维文字表，否则太乱。
                            if (string.IsNullOrWhiteSpace(st) == false && (st.Contains("｜") || st.Contains("|")) && newQuestion.Materials.Count > 0)
                            {
                                if (newQuestion.Materials[newQuestion.Materials.Count - 1].StartsWith("＜＜材料＞＞") && st.StartsWith("＜＜问题＞＞") == false)
                                {
                                    newQuestion.Materials[newQuestion.Materials.Count - 1] += ("\n" + st);
                                }
                            }
                        }
                    }

                    questions.Add(newQuestion);
                }

                return questions;
            }
            #endregion 处理材料题

            if (baseQuestionText == null || baseQuestionText.Length == 0) return questions;

            // baseQuestionText=baseQuestionText.replace("\n", "").replace("\r",
            // "");
            // 不能在此处替换，否则不便找出哪些是答案文本了。


            string[] titleAndAnswers = baseQuestionText.Split(new string[1] { "答案＞＞" }, StringSplitOptions.None);

            if (titleAndAnswers.Length == 1)
            {
                if (titleAndAnswers[0].StartsWith("试题＞＞"))
                {
                    titleAndAnswers[0] = titleAndAnswers[0].Substring(4);
                }

                if (titleAndAnswers[0].StartsWith("#"))
                {
                    // 以#开头的标题也保留
                    questions.Add(new Question(titleAndAnswers[0]));

                    return questions;
                }
                else
                {
                    //填空题，不专门提供“答案＞＞”项
                    var title = titleAndAnswers[0].Replace("〓", "").Trim(new char[] { ' ', '　', '\t' });

                    if (multiFillBlankQuestions)
                    {
                        Question question = new Question(title, title);
                        questions.Add(question);
                        return questions;//填空题哪怕有多项，也只返回一个试题。这样便于课堂演示。2013年9月5日
                    }
                    else
                    {
                        //分解每一个填空项为一道试题。且最后用混淆顺序。
                        List<String> questionTitlesList = BaseQuestion.BuildQuestionTitles(titleAndAnswers[0]);
                        List<Question> fillBlankQuestions = new List<Question>();
                        for (int i = 0; i < questionTitlesList.Count; i++)
                        {
                            Question question = new Question(questionTitlesList[i], string.Empty);
                            fillBlankQuestions.Add(question);
                        }

                        // 使用随机数混淆顺序。
                        if (choiceItemsConfounded)
                        {
                            int[] random = L.GetRandomIntArray(fillBlankQuestions.Count);
                            foreach (int i in random)
                            {
                                fillBlankQuestions[i].OrderNumber = random[i];
                            }

                            fillBlankQuestions.Sort(new ComparsionQuestion());
                        }
                        questions.AddRange(fillBlankQuestions);

                        return questions;
                    }
                }
            }

            if (titleAndAnswers.Length > 1)
            {
                BaseQuestion baseQuestion = new BaseQuestion();
                if (titleAndAnswers[0].StartsWith("试题＞＞"))
                {
                    titleAndAnswers[0] = titleAndAnswers[0].Substring(4);
                }

                baseQuestion.BaseQuestionTitle = titleAndAnswers[0].Replace("〓", "").Trim(new char[] { ' ', '　', '\t', });
                // 第一个片段是试题题干（Title），其余每段是一个“答案组”，每个“答案组”中包括一个答案、一个或多个“错项”。

                // 源文本中一个选择题如果存在多个填充项，则会被拆解为多个试题。每个填充项对应一个答案及一到多个错项。
                List<String> questionTitlesList = BaseQuestion.BuildQuestionTitles(titleAndAnswers[0]);

                if (questionTitlesList.Count == titleAndAnswers.Length - 1)
                {
                    for (int i = 0; i < titleAndAnswers.Length - 1; i++)
                    {
                        Question question = new Question(questionTitlesList[i], titleAndAnswers[i + 1]);
                        questions.Add(question);
                    }

                    return questions;
                }
                else
                {
                    //不等要么是填空题，要么是主观题。判断题是一种特殊的选择题，按选择题来。
                    if (titleAndAnswers.Length == 1)//只有title，填空
                    {
                        for (int i = 0; i < questionTitlesList.Count; i++)
                        {
                            Question question = new Question(questionTitlesList[i], string.Empty);
                            questions.Add(question);
                        }
                    }
                    else
                    {
                        //如果是主观题（有答案无填充项），则questionTitlesList的值只有一个。
                        //一个主观题可以有多个答案
                        for (int i = 0; i < questionTitlesList.Count; i++)
                        {
                            Question question = new Question(questionTitlesList[i], titleAndAnswers);
                            questions.Add(question);
                        }
                    }
                }
            }

            return questions;
        }

        public static string FormatSubjectiveText(string src)
        {
            if (string.IsNullOrWhiteSpace(src)) return "";

            var pieces = Utils.Text.SplitToPiecesByRegex(@"　　试题＞＞|＜＜材料＞＞|＜＜出处＞＞|＜＜问题＞＞|　　答案＞＞|　　解析＞＞|〓〓〓〓〓〓", src);

            if (pieces == null || pieces.Count <= 0) return "";

            var sb = new StringBuilder();

            var replace = false;
            foreach (var p in pieces)
            {
                if (p.IsMartchText && (p.SourceText.Contains("　　答案＞＞") || p.SourceText.Contains("　　解析＞＞")))
                {
                    replace = true;
                    sb.Append(p.SourceText);
                    continue;
                }

                if (p.IsMartchText && p.SourceText == "〓〓〓〓〓〓")
                {
                    sb.Append(p.SourceText + "\r\n");
                    break;
                }

                if (replace)
                {
                    var answerTxt = Regex.Replace(p.SourceText, @"([ 　\t]{0,}(\r\n|\n|\r)[ 　\t]{0,}){1,}", "<br>").TrimEnd(new char[] { ' ', '　', '\t', '\r', '\n' });
                    if (answerTxt.EndsWith("<br>"))
                    {
                        answerTxt = answerTxt.Substring(0, answerTxt.Length - 4);
                    }
                    answerTxt += "\r\n";
                    sb.Append(answerTxt);
                    replace = false;
                }
                else
                {
                    sb.Append(p.SourceText);
                }
            }
            return sb.ToString();
        }

        private string baseQuestionTitle;
        /// <summary>
        /// 试题标题（题干）文本。
        /// </summary>
        public string BaseQuestionTitle
        {
            get { return this.baseQuestionTitle; }
            set { this.baseQuestionTitle = value; }
        }

        /// <summary>
        /// 这是真正使用的试题题干。只包括一个填充项。因为会产生多个题干，所以放在BaseQuestion类中而不是Question类中。
        /// </summary>
        /// <param name="baseQuestionTitleString">题干文本。</param>
        /// <returns></returns>
        private static List<string> BuildQuestionTitles(string baseQuestionTitleString)
        {
            if (baseQuestionTitleString == null || baseQuestionTitleString.Length <= 0) return null;

            List<String> list = new List<String>();

            int startBracket = -1;
            int endBracket = -1;

            startBracket = baseQuestionTitleString.IndexOf('【');
            endBracket = baseQuestionTitleString.IndexOf('】');

            if (startBracket < 0 || endBracket < 0)
            {
                //主观题没有填充项。
                list.Add(baseQuestionTitleString.Replace("【", "").Replace("】", "")//.Replace("\r", "").Replace("\n", "")
                        .Trim(new char[] { ' ', '　', '\t' }));
                return list;
            }

            while (startBracket >= 0 && endBracket >= 0 && startBracket < endBracket)
            {
                StringBuilder sBuilder = new StringBuilder();

                sBuilder.Append(baseQuestionTitleString.Substring(0, startBracket).Replace("【", "").Replace("】", "")//.Replace("\r", "").Replace("\n", "")
                        .Trim(new char[] { ' ', '　', '\t' }));

                //string fillBlankText = baseQuestionHeaderString.Substring(startBracket + 1, endBracket - startBracket - 1);//+1-1是为了去除首尾的方括弧。【】

                //StringBuilder sBuilder2 = new StringBuilder();
                //sBuilder2.Append("<Span Tag=\"FillBlank\">");
                //sBuilder2.Append(fillBlankText);
                //sBuilder2.Append("</Span>");

                string fillBlankText = baseQuestionTitleString.Substring(startBracket, endBracket - startBracket + 1);//+1-1是为了去除首尾的方括弧。【】

                StringBuilder sBuilder2 = new StringBuilder();
                sBuilder2.Append(fillBlankText);

                sBuilder.Append(sBuilder2.ToString());
                sBuilder.Append(baseQuestionTitleString.Substring(endBracket).Replace("【", "").Replace("】", "")//.Replace("\r", "").Replace("\n", "")
                        .Trim(new char[] { ' ', '　', '\t', }));

                list.Add(sBuilder.ToString());

                startBracket = baseQuestionTitleString.IndexOf('【', endBracket);
                endBracket = baseQuestionTitleString.IndexOf('】', endBracket + 1);
            }

            StringBuilder stringBuilder = new StringBuilder();
            foreach (string text in list)
            {
                stringBuilder.Append(text);
            }

            return list;
        }
    }

}
